package com.smart.speaker.websocket;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.tools.ToolCallBase;
import com.alibaba.dashscope.tools.ToolCallFunction;
import com.smart.speaker.util.BeanUtils;
import com.smart.speaker.util.StrUtils;
import com.smart.speaker.websocket.chat.Chat;
import com.smart.speaker.websocket.chat.GameWord;
import com.smart.speaker.websocket.chat.Normal;
import com.smart.speaker.websocket.tool.Tool;
import com.smart.speaker.websocket.tool.ToolResp;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

@Slf4j
public class ChatHandler {

    private final SynthesisHandler synthesizer;
    private final MessageHandler messageHandler;

    private ChatState state;

    private final Map<ChatState, Chat> chatMap;

    public ChatHandler(Generation generation,
                       SynthesisHandler synthesizer, MessageHandler messageHandler,
                       SessionState sessionState) {
        this.synthesizer = synthesizer;
        this.messageHandler = messageHandler;
        this.state = ChatState.NORMAL;
        chatMap = Map.of(ChatState.NORMAL, new Normal(generation, sessionState, this),
                ChatState.GAME_WORD, new GameWord(generation, this));
    }

    public void chat(String req) {
        Chat chat = chatMap.get(state);
        chat.chat(req);
    }

    public void secondChat() {
        Chat chat = chatMap.get(state);
        chat.secondChat();
    }

    public void synthesizer(String response) {
        if (response == null) {
            return;
        }
        log.info("Result: {}", response);
        messageHandler.sendMessage("tts", "sentence_start", response);
        synthesizer.synthesizer(response);
    }

    public void executeTool(List<ToolCallBase> toolList) {
        StringBuilder toolName = new StringBuilder();
        StringBuilder toolArgs = new StringBuilder();
        try {
            for (ToolCallBase tool : toolList) {
                if ("function".equals(tool.getType())) {
                    ToolCallFunction func = (ToolCallFunction) tool;
                    String name = func.getFunction().getName();
                    if (name != null) {
                        toolName.append(name);
                    }
                    String args = func.getFunction().getArguments();
                    if (args != null) {
                        toolArgs.append(args);
                    }
                }
            }
            String name = toolName.toString().trim();
            String args = toolArgs.toString().trim();
            if (StrUtils.isEmpty(name)) {
                return;
            }
            log.info("执行工具 {} - {}", name, args);
            if (!BeanUtils.containsBean(name)) {
                log.warn("找不到名为 {} 的工具", name);
                return;
            }
            Tool tool = BeanUtils.getBean(name, Tool.class);
            ToolResp toolResp = tool.call(args);
            if (toolResp.getState() != null) {
                state = toolResp.getState();
            }
            if (Tool.Type.RESPONSE.equals(toolResp.getType())) {
                synthesizer(toolResp.getContent());
            } else if (Tool.Type.REQLLM.equals(toolResp.getType())) {
                secondChat();
            }
        } catch (Exception e) {
            log.error("工具调用出错name=[{}]args=[{}]", toolName, toolArgs, e);
        }
    }
}
